#include "fxcc/core/graph/opengl3/ShaderFile.h"

using namespace fxcc::graph::opengl3;

bool fxcc::graph::opengl3::ShaderFile::CreateFrom(const char* code, int type)
{
	this->m_Id = glCreateShader(type);
	glShaderSource(m_Id, 1, &code, NULL);
	glCompileShader(m_Id);
	bool res = checkCompileErrors(m_Id, GetShaderType(type));
	return res;
}

std::string fxcc::graph::opengl3::ShaderFile::GetShaderType(int type)
{
	return g_ShaderDescs[type];
}

void fxcc::graph::opengl3::ShaderFile::Release()
{
	glDeleteShader(m_Id);
}


std::map<int, std::string > fxcc::graph::opengl3::ShaderFile::g_ShaderDescs =
{

	{GL_VERTEX_SHADER,"GL_VERTEX_SHADER"},
	{GL_FRAGMENT_SHADER,"GL_FRAGMENT_SHADER"},
	{GL_GEOMETRY_SHADER,"GL_GEOMETRY_SHADER"},
	{GL_COMPUTE_SHADER,"GL_COMPUTE_SHADER"},
	{GL_TESS_CONTROL_SHADER,"GL_TESS_CONTROL_SHADER"},
	{GL_TESS_EVALUATION_SHADER,"GL_TESS_EVALUATION_SHADER"}

};

bool fxcc::graph::opengl3::ShaderFile::checkCompileErrors(unsigned int shader, std::string type)
{
	GLint success;
	GLchar infoLog[ZTC_MAX_LEN];
	if (type != "PROGRAM")
	{
		glGetShaderiv(shader, GL_COMPILE_STATUS, &success);
		if (!success)
		{
			glGetShaderInfoLog(shader, ZTC_MAX_LEN, NULL, infoLog);
			ztclog::info("ERROR::SHADER_COMPILATION_ERROR of type: %s \n %s", type.c_str(), infoLog);
		}
	}
	else
	{
		glGetProgramiv(shader, GL_LINK_STATUS, &success);
		if (!success)
		{
			glGetProgramInfoLog(shader, ZTC_MAX_LEN, NULL, infoLog);
			ztclog::info("ERROR::PROGRAM_LINKING_ERROR of type: %s \n %s", type.c_str(), infoLog);
		}
	}
	return success;
};


bool ShaderFile::CreateFromFile(std::string path, int type)
{
	bool gr = true;

	std::ifstream ifs(path, std::ios::in);

	if (!ifs.is_open())
	{
		ztclog::info("cannot open file from %s \n", path.c_str());
		return false;
	}

	ztclog::info("Loading the file %s", path.c_str());

	std::string text = std::string((std::istreambuf_iterator<char>(ifs)),
		(std::istreambuf_iterator<char>()));

	gr = CreateFrom(text.c_str(), type);
	ifs.close();
	return gr;
}

